package threadingexercise;

//通过懒汉模式 来实现 单例模式  是不安全的 三步操作把懒汉模式 变成线程安全的
class SingletonLazy {
        //唯一实例化的本体
        // 3. 加上 volatile ，禁止指令重排序，保证后续线程拿到的是完成的对象
        volatile private static SingletonLazy instance = null;


        //获取到实例的方法
        public static SingletonLazy getInstance() {
            //这个条件，判断是否要加锁。如果对象已经有了，就不必加锁了
            //若没有这个条件，任何时候调用getInstance()，都会触发锁竞争
            //其实只要第一个new 好了对象之后，就没有线程安全问题，就不需要加锁了
            // 2. 双重 if 操作
            if(instance == null) {
                //1. 进行加锁操作，把 if 和 new操作变成原子性的
                synchronized(SingletonLazy.class) {
                    //
                    if(instance == null) {
                        instance = new SingletonLazy();
                    }
                }
            }
            return instance;
        }

        //构造方法私有化，就可以防止外部 new 实例，但是private类的内部可以调用构造方法
        private SingletonLazy() { }

}


public class ThreadDemo18 {
    public static void main(String[] args) {
        //此时 这两个对象是同一个
        SingletonLazy s1 = SingletonLazy.getInstance();
        SingletonLazy s2 = SingletonLazy.getInstance();
        System.out.println(s1 == s2); // true
    }
}
